using System;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace stsdev
{

    public class ManifestBuilder
    {

        private const string nsSP = "http://schemas.microsoft.com/sharepoint/";

        public static void Create(string FilePath, bool AssemblyDeployment)
        {
            Create(FilePath, AssemblyDeployment, SolutionBuilder.ResetWebServer);
        }

        public static void Create(string FilePath, bool AssemblyDeployment, bool IISRESET)
        {

            StreamWriter manifestStream = new StreamWriter(FilePath);
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            settings.Indent = true;
            settings.NewLineOnAttributes = false;
            settings.NewLineHandling = NewLineHandling.None;
            XmlWriter writer = XmlWriter.Create(manifestStream, settings);
            writer.WriteStartDocument();

            writer.WriteComment("Manifest created STSDEV utility at " + DateTime.Now.ToString());
            writer.WriteStartElement("Solution", nsSP);
            // add solution ID
            writer.WriteAttributeString("SolutionId", SolutionBuilder.SolutionId);
            writer.WriteAttributeString("ResetWebServer", IISRESET.ToString());

            if (Directory.Exists(Globals.FeaturesFolder))
            {
                // write feature manifests
                writer.WriteComment("Feature Manifest files");
                writer.WriteStartElement("FeatureManifests");
                // write FEATURE Files
                foreach (string directory in Directory.GetDirectories(Globals.FeaturesFolder))
                {
                    WriteFeatureManifestFile(writer, directory.Substring((Globals.FeaturesFolder + @"\").Length) + @"\feature.xml");
                }
                writer.WriteEndElement(); // </FeatureManifest>
            }

            if (Directory.Exists(Globals.TemplatesFolder))
            {
                // write TEMPLATE Files
                writer.WriteComment("TEMPLATE files");
                writer.WriteStartElement("TemplateFiles");
                WriteTemplateFiles(writer);
                writer.WriteEndElement(); // </TemplateFiles>
            }

            if (Directory.Exists(Globals.IsapiFolder) || Directory.Exists(Globals.ResourcesFolder))
            {
                // write Root Files
                writer.WriteComment("Root files");
                writer.WriteStartElement("RootFiles");
                WriteRootFiles(writer);
                writer.WriteEndElement(); // </RootFiles>
            }

            if (SolutionBuilder.AssemblyDeployment)
            {
                // write Assembly Files
                writer.WriteComment("Assembly files");
                writer.WriteStartElement("Assemblies");
                foreach (SolutionAssembly asm in SolutionBuilder.Assemblies)
                {
                    WriteAssembly(writer, asm);
                }
                writer.WriteEndElement(); // </Assemblies>
            }

            if ((SolutionBuilder.CasPermissions) &&
                 (SolutionBuilder.CasPermissionsNode != null))
            {
                writer.WriteComment("Code Access Security Permissions");
                WriteCasPermissions(writer);
            }

            if (SolutionBuilder.DwpFilesNode != null)
            {
                writer.WriteComment("NonFeature Web Parts");
                WriteDwpFiles(writer);
            }

            writer.WriteEndElement(); // </Solution>
            writer.WriteEndDocument();
            writer.Close();
            manifestStream.Close();

        }

        private static void WriteDwpFiles(XmlWriter writer)
        {
            if (SolutionBuilder.DwpFilesNode == null)
            {
                Console.WriteLine("Solution has no webpart Files in SolutionConfig.xml");
                return;
            }
            writer.WriteStartElement("DwpFiles");
            foreach (XmlNode child in SolutionBuilder.DwpFilesNode)
            {
                writer.WriteStartElement("DwpFile");
                foreach (XmlAttribute attr in child.Attributes)
                {
                    writer.WriteAttributeString(attr.Name, attr.Value);
                }
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        static private void WriteFeatureManifestFile(XmlWriter writer, string path)
        {
            writer.WriteStartElement("FeatureManifest");
            writer.WriteAttributeString("Location", path);
            writer.WriteEndElement();
        }

        static void WriteTemplateFiles(XmlWriter writer)
        {
            EnumerateTemplateDirectory(writer, Globals.TemplatesFolder);
        }

        static void EnumerateTemplateDirectory(XmlWriter writer, string path)
        {

            foreach (string file in Directory.GetFiles(path))
            {
                if (!file.Contains("FEATURES"))
                {
                    if ((File.GetAttributes(file) & FileAttributes.Hidden) == FileAttributes.Hidden)
                    {
                        writer.WriteComment("Skipping Template file " + file);
                    }
                    else
                    {
                        writer.WriteStartElement("TemplateFile");
                        writer.WriteAttributeString("Location", file.Substring((Globals.TemplatesFolder + @"\").Length));
                        writer.WriteEndElement();
                    }
                }
            }

            foreach (string folder in Directory.GetDirectories(path))
            {
                if (!folder.Contains("FEATURES"))
                {
                    EnumerateTemplateDirectory(writer, folder);
                }
            }
        }

        static void WriteRootFiles(XmlWriter writer)
        {
            EnumerateRootFilesDirectory(writer, Globals.RootFilesFolder);
        }

        static void EnumerateRootFilesDirectory(XmlWriter writer, string path)
        {
            foreach (string file in Directory.GetFiles(path))
            {
                if (!file.Contains("TEMPLATE"))
                {
                    if ((File.GetAttributes(file) & FileAttributes.Hidden) == FileAttributes.Hidden)
                    {
                        writer.WriteComment("Skipping Template file " + file);
                    }
                    else
                    {
                        writer.WriteStartElement("RootFile");
                        writer.WriteAttributeString("Location", file.Substring((Globals.RootFilesFolder + @"\").Length));
                        writer.WriteEndElement();
                    }
                }
            }

            foreach (string folder in Directory.GetDirectories(path))
            {
                if (!folder.Contains("TEMPLATE"))
                {
                    EnumerateRootFilesDirectory(writer, folder);
                }
            }
        }

        static void WriteAssembly(XmlWriter writer, SolutionAssembly asm)
        {
            writer.WriteStartElement("Assembly"); //<Assembly Location="..." DeploymentTarget="...">
            writer.WriteAttributeString("Location", asm.Location);
            writer.WriteAttributeString("DeploymentTarget", asm.DeploymentTarget);
            if (
                //SolutionBuilder.SafeControlSettings &&
                asm.SafeControlEntries.Count > 0)
            {
                writer.WriteStartElement("SafeControls");
                foreach (SolutionSafeControlEntry entry in asm.SafeControlEntries)
                {
                    writer.WriteStartElement("SafeControl");
                    writer.WriteAttributeString("Assembly", entry.Assembly);
                    writer.WriteAttributeString("Namespace", entry.Namespace);
                    writer.WriteAttributeString("TypeName", entry.TypeName);
                    writer.WriteAttributeString("Safe", entry.Safe);
                    writer.WriteEndElement(); // </SafeControl>
                }
                writer.WriteEndElement();
            }
            if (asm.ClassResourceEntries.Count > 0)
            {
                writer.WriteStartElement("ClassResources");
                foreach (ClassResourceEntry resourceEntry in asm.ClassResourceEntries)
                {
                    writer.WriteStartElement("ClassResource");
                    writer.WriteAttributeString("Location", resourceEntry.Location);
                    writer.WriteAttributeString("FileName", resourceEntry.FileName);
                    writer.WriteEndElement(); //</ClassResource>
                }
                writer.WriteEndElement(); //</ClassResources>
            }


            writer.WriteEndElement(); //</Assembly>
        }

        static void WriteCasPermissions(XmlWriter writer)
        {
            if (SolutionBuilder.CasPermissionsNode == null)
            {
                Console.WriteLine("Solution has no CAS Permissions in SolutionConfig.xml");
                return;
            }
            writer.WriteStartElement("CodeAccessSecurity");
            writer.WriteStartElement("PolicyItem");
            writer.WriteStartElement("PermissionSet");
            writer.WriteAttributeString("class", "NamedPermissionSet");
            writer.WriteAttributeString("version", "1");
            writer.WriteAttributeString("Name", SolutionBuilder.TargetName);
            // write out each CAS permission as an IPermission element
            foreach (XmlNode child in SolutionBuilder.CasPermissionsNode)
            {
                writer.WriteStartElement("IPermission");
                foreach (XmlAttribute attr in child.Attributes)
                {
                    writer.WriteAttributeString(attr.Name, attr.Value);
                }
                writer.WriteEndElement(); // </IPermission>
            }
            writer.WriteEndElement(); // </PermissionSet>

            writer.WriteStartElement("Assemblies");
            writer.WriteStartElement("Assembly");
            writer.WriteAttributeString("Name", SolutionBuilder.TargetName);
            writer.WriteEndElement(); // </Assembly>
            writer.WriteEndElement(); // </Assemblies>
            writer.WriteEndElement(); // </PolicyItem>
            writer.WriteEndElement(); // </CodeAccessSecurity>      
        }

    }

}
